import os
import time

import ujson

from django.db.models import Q
from django.http import StreamingHttpResponse
from django.shortcuts import redirect
from django.utils import timezone
from django_redis import get_redis_connection
from rest_framework.decorators import api_view
from rest_framework.generics import ListAPIView
from rest_framework.response import Response

from carsys import app
from search.models import Record
from search.serializers import RecordSerializer
from search.utils import gen_md5_hex, POOL


def download_pdf(request):
    full_path = os.path.join(os.path.dirname(__file__), 'images/Redis开发与运维.pdf')
    file = open(full_path, 'rb')
    file_iter = iter(lambda: file.read(512), b'')
    resp = StreamingHttpResponse(file_iter)
    resp['content-type'] = 'application/pdf'
    resp['content-disposition'] = 'attachment; filename="Redis.pdf"'
    return resp


def show_index(request):
    return redirect('/static/html/index.html')


class RecordView(ListAPIView):
    # queryset = Record.objects.all()
    serializer_class = RecordSerializer

    def get_queryset(self):
        queryset = Record.objects.filter(is_deleted=False) \
            .defer('is_deleted', 'deleted_time', 'updated_time') \
            .select_related('car').order_by('-makedate')
        keyword = self.request.GET.get('keyword')
        if keyword:
            queryset = queryset.filter(
                Q(car__carno__iexact=keyword) | Q(car__owner__contains=keyword)
            )
        return queryset

    def list(self, request, *args, **kwargs):
        # 生成缓存的key
        path = gen_md5_hex(request.get_full_path())
        key = f'carsys:search:views:records:{path}'
        # 获取原生Redis连接（Redis对象）
        redis_cli = get_redis_connection()
        # 通过key获取缓存中的value
        data = redis_cli.get(key)
        if data:
            # 如果从缓存中拿到了数据直接反序列化生成响应
            resp = Response(ujson.loads(data))
        else:
            # 如果缓存中没有拿到数据，那么就执行查询获取数据并写入缓存
            resp = super().list(request, *args, **kwargs)
            redis_cli.set(key, ujson.dumps(resp.data), ex=300)
        return resp


# # @method_decorator(decorator=cache_page(timeout=300, cache='default'), name='list')
# # @method_decorator(decorator=cache_page(timeout=1800, cache='default'), name='retrieve')
# class RecordViewSet(ReadOnlyModelViewSet):
#     queryset = Record.objects.all()
#     serializer_class = RecordSerializer
#
#     def list(self, request, *args, **kwargs):
#         path = gen_md5_hex(request.get_full_path())
#         key = f'carsys:search:views:records:{path}'
#         redis_cli = get_redis_connection()
#         data = redis_cli.get(key)
#         if data:
#             resp = Response(ujson.loads(data))
#         else:
#             resp = super().list(request, *args, **kwargs)
#             redis_cli.set(key, ujson.dumps(resp.data), ex=300)
#         return resp
#
#     def get_queryset(self):
#         queryset = Record.objects.filter(is_deleted=False) \
#             .defer('is_deleted', 'deleted_time', 'updated_time') \
#             .select_related('car').order_by('-makedate')
#         keyword = self.request.GET.get('keyword')
#         if keyword:
#             queryset = queryset.filter(
#                 Q(car__carno__iexact=keyword) | Q(car__owner__contains=keyword)
#             )
#         return queryset


@api_view(('PUT', 'PATCH', 'DELETE'))
def handle_record(request, rno):
    if request.method == 'DELETE':
        return delete_record(rno)
    else:
        return update_record(rno)


@app.task
def delay_clear_cache(key_prefix, delay=0):
    if delay > 0:
        time.sleep(delay)
    redis_cli = get_redis_connection()
    keys = redis_cli.keys(f'{key_prefix}*')
    for key in keys:
        redis_cli.delete(key)


def update_record(rno):
    record = Record.objects.filter(no=rno).first()
    if record and not record.dealt:
        delay_clear_cache('carsys:search:views:records:')
        record.dealt = True
        record.updated_time = timezone.now()
        record.save()
        # 执行异步任务的代码相当于是消息的生产者（向消息队列中放入一个消息（任务））
        # 受理任务需要启动消息的消费者（通常在另外的服务器节点上进行）
        # celery -A carsys worker -l debug
        delay_clear_cache.delay('carsys:search:views:records:', 1)
        # POOL.submit(delay_clear_cache, 'carsys:search:views:records:', 1)
    return Response(status=200)


def delete_record(rno):
    record = Record.objects.filter(no=rno).first()
    if record and record.dealt:
        delay_clear_cache('carsys:search:views:records:')
        record.is_deleted = True
        record.deleted_time = timezone.now()
        record.save()
        POOL.submit(delay_clear_cache, 'carsys:search:views:records:', 1)
    return Response(status=204)
